﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

using RZD_maps.MapPath.Models;

using GMap.NET;
using GMap.NET.WindowsPresentation;

namespace RZD_maps.MapPath.Views
{
    /// <summary>
    /// Interaction logic for View.xaml
    /// </summary>
    public partial class View : UserControl
    {
        public View()
        {
            InitializeComponent();
            MainMap2.Zoom = 10;
        }

        private void OnSelectedItemChanged(object sender, Hardcodet.Wpf.GenericTreeView.RoutedTreeItemEventArgs<Models.BaseCategory> e)
        {
            DisplayRoute();
        }

        private void MainMap2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            System.Windows.Point p = e.GetPosition(MainMap2);
            PointLatLng latlng = MainMap2.FromLocalToLatLng((int)p.X, (int)p.Y);
            textBlockLat.Text = latlng.Lat.ToString();
            textBlockLng.Text = latlng.Lng.ToString();
        }

        #region context menu command handling

        /// <summary>
        /// Creates a sub category for the clicked item
        /// and refreshes the tree.
        /// </summary>
        private void AddCategory(object sender, ExecutedRoutedEventArgs e)
        {
            //get the processed item
            BaseCategory parent = GetCommandItem();

            //create a sub category
            string name = textBlockName.Text.Trim();// ShowInputDialog(null);
            if (string.IsNullOrEmpty(name)) return;
            try
            {
                BaseCategory subCategory = new BaseCategory(name, parent);
                double val;
                val = 0.0;
                Double.TryParse(textBlockLat.Text, out val);
                subCategory.Lat = val;
                val = 0.0;
                Double.TryParse(textBlockLng.Text, out val);
                subCategory.Lng = val;
                val = 0.0;
                Double.TryParse(textBlockVelocity.Text, out val);
                subCategory.Velocity = val;
                parent.SubCategories.Add(subCategory);
                subCategory.SubCategories.Add(new BaseCategory(string.Format("Долгота: {0}", subCategory.Lng), subCategory));
                subCategory.SubCategories.Add(new BaseCategory(string.Format("Широта: {0}", subCategory.Lat), subCategory));
                subCategory.SubCategories.Add(new BaseCategory(string.Format("{1}: Скорость : {0}", subCategory.Velocity, name), subCategory));
                //make sure the parent is expanded
                CategoryTree.TryFindNode(parent).IsExpanded = true;
            }
            catch
            {
            }
            DisplayRoute();
            //NOTE this would be an alternative to force layout preservation
            //even if the PreserveLayoutOnRefresh property was false:
            //TreeLayout layout = CategoryTree.GetTreeLayout();
            //CategoryTree.Refresh(layout);

            //Important - mark the event as handled
            e.Handled = true;
        }


        /// <summary>
        /// Checks whether it is allowed to delete a category, which is only
        /// allowed for nested categories, but not the root items.
        /// </summary>
        private void EvaluateCanDelete(object sender, CanExecuteRoutedEventArgs e)
        {
            //get the processed item
            BaseCategory item = GetCommandItem();

            e.CanExecute = (item.ParentCategory != null) && (item.ParentCategory.ParentCategory == null);
            e.Handled = true;
        }


        /// <summary>
        /// Deletes the currently processed item. This can be a right-clicked
        /// item (context menu) or the currently selected item, if the user
        /// pressed delete.
        /// </summary>
        private void DeleteCategory(object sender, ExecutedRoutedEventArgs e)
        {
            //get item
            BaseCategory item = GetCommandItem();

            //remove from parent
            item.ParentCategory.SubCategories.Remove(item);

            //mark event as handled
            e.Handled = true;
        }


        /// <summary>
        /// Determines the item that is the source of a given command.
        /// As a command event can be routed from a context menu click
        /// or a short-cut, we have to evaluate both possibilities.
        /// </summary>
        /// <returns></returns>
        private BaseCategory GetCommandItem()
        {
            //get the processed item
            ContextMenu menu = CategoryTree.NodeContextMenu;
            if (menu.IsVisible)
            {
                //a context menu was clicked
                TreeViewItem treeNode = (TreeViewItem)menu.PlacementTarget;
                return (BaseCategory)treeNode.Header;
            }
            else
            {
                //the context menu is closed - the user has pressed a shortcut
                return CategoryTree.SelectedItem;
            }
        }

        #endregion

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (CategoryTree.SelectedItem == null) return;
            if (CategoryTree.SelectedItem.ParentCategory != null) return;
            try
            {
                string name = textBlockName.Text.Trim();// ShowInputDialog(null);
                if (string.IsNullOrEmpty(name)) return;
                BaseCategory subCategory = new BaseCategory(name, CategoryTree.SelectedItem);
                double val;
                val = 0.0;
                Double.TryParse(textBlockLat.Text, out val);
                subCategory.Lat = val;
                val = 0.0;
                Double.TryParse(textBlockLng.Text, out val);
                subCategory.Lng = val;
                val = 0.0;
                Double.TryParse(textBlockVelocity.Text, out val);
                subCategory.Velocity = val;
                CategoryTree.SelectedItem.SubCategories.Add(subCategory);
                subCategory.SubCategories.Add(new BaseCategory(string.Format("Долгота: {0}", subCategory.Lng), subCategory));
                subCategory.SubCategories.Add(new BaseCategory(string.Format("Широта: {0}", subCategory.Lat), subCategory));
                subCategory.SubCategories.Add(new BaseCategory(string.Format("{1}: Скорость : {0}", subCategory.Velocity, name), subCategory));
                //make sure the parent is expanded
                CategoryTree.TryFindNode(CategoryTree.SelectedItem).IsExpanded = true;
            }
            catch
            {
            }
            DisplayRoute();
        }

        private struct routeData
        {
            public PointLatLng point;
            public double velocity;
        }

        private void DisplayRoute()
        {
            double ESRIShapepolylat;
            double ESRIShapepolylong;
            double velocity1 = 0.0;
            double velocity2 = 0.0;
            List<PointLatLng> routePoints = new List<PointLatLng>();

            List<routeData> routePointsdt = new List<routeData>();

            MainMap2.Markers.Clear();
            foreach (var item in CategoryTree.SelectedItem.SubCategories)
            {
                ESRIShapepolylat = item.Lat;
                ESRIShapepolylong = item.Lng;
                routePointsdt.Add(new routeData() { point = new PointLatLng(ESRIShapepolylat, ESRIShapepolylong), velocity = item.Velocity });
            }
            if (routePointsdt.Count < 2) return;
            int i = 0;
            bool bNeedMarker = false;
            bool bFirst = true;
            while (i < routePointsdt.Count-1)
            {
                routePoints.Add(routePointsdt[i].point);
                routePoints.Add(routePointsdt[i+1].point);
                i += 1;
                MapRoute r = new MapRoute(routePoints, "");
                GMapMarker m = new GMapMarker(routePoints[0]);
                m.Route.AddRange(r.Points);
                m.RegenerateRouteShape(MainMap2);
                (m.Shape as System.Windows.Shapes.Path).Opacity = 1.0;
                Brush brsh = System.Windows.Media.Brushes.Green;

                bNeedMarker = false;
                if (bFirst == true)
                {
                    velocity1 = routePointsdt[i].velocity;
                    velocity2 = routePointsdt[i].velocity;
                    bNeedMarker = true;
                    bFirst = false;
                }
                else
                {
                    velocity1 = velocity2;
                    velocity2 = routePointsdt[i].velocity;
                    if (velocity2 != velocity1)
                        bNeedMarker = true;
                }
               
                if (routePointsdt[i].velocity < 30)
                    brsh = System.Windows.Media.Brushes.Red;
                else if (routePointsdt[i].velocity < 50)
                    brsh = System.Windows.Media.Brushes.Orange;
                else if (routePointsdt[i].velocity < 60)
                    brsh = System.Windows.Media.Brushes.Yellow;
                else
                    brsh = System.Windows.Media.Brushes.Green; // new SolidColorBrush(Color.FromRgb(255, 0, 0));
                (m.Shape as System.Windows.Shapes.Path).Stroke = brsh;
                
                (m.Shape as System.Windows.Shapes.Path).StrokeThickness = 2;//1;//4;
                //m.RegenerateRouteShape(MainMap2);
                //(m.Shape as System.Windows.Shapes.Path).Stroke = brsh;
                //(m.Shape as System.Windows.Shapes.Path).StrokeThickness = 4;
                //m.RegenerateRouteShape(map);
                //m.ZIndex = -1;
                //m.RegenerateRouteShape(MainMap2);

                MainMap2.Markers.Add(m);
                if (bNeedMarker)
                {
                    GMapMarker marker = new GMapMarker(routePoints[0]);
                    marker.ZIndex = 50;
                    //var v = new CircleVisual(marker, Brushes.Red);
                    var v = new CircleVisual(marker, brsh);  
                    v.Text = velocity2.ToString();
                    v.Angle = 180;//0;
                    v.Stroke = new Pen(Brushes.Gray, 2.0);
                    marker.Shape = v;
                    MainMap2.Markers.Add(marker);
                }
                routePoints.Clear();
            }
            
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Model mdl = (Model)this.FindResource("Model");
            //MapPathUtil.SerializeObjectToXML<ObservableCollection<BaseCategory>>(mdl.Categories, @"c:\temp\data.xml");
            MapPathUtil.SerializeObject(mdl.Categories, @"data.xml");
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            Model mdl = (Model)this.FindResource("Model");
            //foreach (var it in mdl.Categories)
            //{
            //    while (it.SubCategories.Count() > 0)
            //    {
            //        it.SubCategories.Remove(it.SubCategories[0]);
            //    }
            //}
            //MapPathUtil.DeserializeObject(mdl.Categories, @"data.xml");
            //mdl.ra
            mdl.RefreshData();
            DisplayRoute();
        }
    }
}
